import {isEmpty, isNil, type} from 'ramda'
import {RW} from "./QRW";
/**
 * 区间判断
 * @param value
 * @param range
 * @return {boolean|void|*}
 *
 * @example
 * isRangeIn(55,'[50,60]')
 * 中括号开区间，小括号闭区间，大括号枚举匹配，直接填入数值判断等于
 */
export const isRangeIn = function (value, range) {
    if(typeof range === 'number') range = range.toString()
    if(!range) return false // range为空时默认错误
    if(!value && value !== 0) return false // value为空时默认错误
    if(!isNaN(value)) value = Number(value) // value不为number时强转一下
    else {
        console.error('isRangeIn first param "value" is NaN')
        return false
    }
    let isContainMin = false
    let isContainMax = false
    let isGTMin = false
    let isLTMax = false
    // 纯数字时相等为真
    if(!isNaN(Number(range))) return value === Number(range)
    // 花括弧时，包含为真
    if(range.includes('{') && range.includes('}')) {
        let arrString = range.replace(/\{|}/g,'')
        let arr = arrString.split(',').map(item => {
            return Number(item)
        })
        return arr.includes(value)
    }
    // 位运算+幂运算（判断第几位是1）
    if(range.includes('&pow')) {
        let string = range.replace(/(&pow)/g,'')
        return !!(value&Math.pow(2,Number(string) - 1))
    }
    // 位运算（与）
    if(range.includes('&')) {
        let string = range.replace(/(&)/g,'')
        return !!(value&Number(string))
    }
    // 开闭区间，运算
    let rangeArr = range.split(',')
    if(rangeArr[0].includes('[')) isContainMin = true
    if(rangeArr[1].includes(']')) isContainMax = true
    let min = rangeArr[0].replace(/\[|]|\(|\)/g,'') || -Infinity
    let max = rangeArr[1].replace(/\[|]|\(|\)/g,'') || Infinity
    if(isContainMin) {
        isGTMin = value >= min
    }else {
        isGTMin = value > min
    }
    if(isContainMax) {
        isLTMax = value <= max

    }else {
        isLTMax = value < max
    }
    return isLTMax && isGTMin
}

/**
 * 判断一个对象是否符合要求
 * @param {{key,value,condition,prop,eval,enum,dateFormat,must,should,matchFuncName}} config
 * @param {{}} data
 * @param {{}} [myFuncMap]
 * @return {boolean|*}
 */
export function matchRules(config, data) {
    if(config.must) {
        return checkMust(config.must, data)
    }
    if(config.should) {
        return checkShould(config.should, data)
    }
    if(config.condition) {
        let left = config.left
        let right = config.right
        if(config.leftKey) {
            left = RW(data)[config.leftKey]
        }
        if(config.rightKey) {
            right = RW(data)[config.rightKey]
        }
        if(config.condition === 'eq') {
            return left === right
        }
        if(config.condition === 'ne') {
            return left !== right
        }
        if(config.condition === 'lt') {
            return left < right
        }
        if(config.condition === 'le') {
            return left <= right
        }
        if(config.condition === 'gt') {
            return left > right
        }
        if(config.condition === 'ge') {
            return left >= right
        }
        if(config.condition === 'in') {
            if(['String', 'Array'].includes(type(right))) {
                return right?.includes(left)
            }else {
                console.error(`${right} is not String|Array`)
                return false
            }
        }
        if(config.condition === 'nin') {
            if(['String', 'Array'].includes(type(right))) {
                return !right?.includes(left)
            }else {
                console.error(`${right} is not String|Array`)
                return false
            }
        }
        if(config.condition === 'has') {
            if(['String', 'Array'].includes(type(left))) {
                return left?.includes(right)
            }else {
                console.error(`${left} is not String|Array`)
                return false
            }
        }
        if(config.condition === 'nhas') {
            if(['String', 'Array'].includes(type(left))) {
                return !left?.includes(right)
            }else {
                console.error(`${left} is not String|Array`)
                return false
            }
        }
        if(config.condition === 'notNull') {
            return !isNil(left) && !isEmpty(left)
        }
        if(config.condition === 'isNull') {
            return isNil(left) || isEmpty(left)
        }
        if(config.condition === 'any') {
            return true
        }
    }
    return true
}

/**
 * 通用条件判断must
 */
export function checkMust(must, row) {
    let result = []
    for(let item of must) {
        result.push(matchRules(item, row))
    }
    return !result.includes(false)
}

/**
 * 通用条件判断should
 */
export function checkShould(should, row) {
    let result = []
    for(let item of should) {
        result.push(matchRules(item, row))
    }
    return result.includes(true)
}

/**
 * 类型判断
 */
export function isType(type, target) {
    let typeList = type.split(',')
    let result = []
    for(let type of typeList) {
        result.push(Object.prototype.toString.call(target) === `[object ${type}]`)
    }
    return result.includes(true)
}
